<template>
  <div class="chartMain real-time-video" :class="`${componentStyle} ${componentStyle}-Style`" :style="boxStyle">
    <div v-if="isDisplay" :id="`chartMain${chartId}`" class="content">
      <div v-if="displayStyle === 'icon'" class="icon-container">
        <el-popover
          :popper-class="`hostsdk-video-popper hostsdk-video-popper-${componentStyle}`"
          placement="right"
          :width="popVideoWidth"
          :popper-style="{
            height: popVideoHeight + 'px',
          }"
          trigger="click"
          @hide="hideVideo()"
          @after-enter="showVideoDialog()"
        >
          <template #reference>
            <div class="icon-content">
              <Icon :conf="icon" />
            </div>
          </template>
          <div :id="`video_container_icon_${widgetInstanceId}`" class="video-group-container">
            <haikang-video
              v-if="isShow"
              ref="haikanVideoRef"
              :prop-camera-index-codes="propCameraIndexCodes"
              :camera-index-code="cameraIndexCode"
              :config="config"
              :width="popVideoWidth"
              :height="popVideoHeight"
              :x="x"
              :y="y"
              is-in-dialog="1"
              :widgetInstanceId="widgetInstanceId"
              :videoId="`${widgetInstanceId}_0`"
              :componentStyle="componentStyle"
              :winContainerPid="winContainerPid"
              :isDesignView="isDesignView"
              :isMashupPreviewVideo="isPreviewVideo"
            />
          </div>
        </el-popover>
      </div>
      <div v-else :id="`video-group-container-${chartId}`" class="video-group-container">
        <div :class="`video-haikan-refresh video-haikan-refresh-${componentStyle}`" @click="refreshVideo">
          <el-icon>
            <Refresh />
          </el-icon>
        </div>
        <haikang-video
          v-if="isShow"
          ref="haikanVideoRef"
          :prop-camera-index-codes="propCameraIndexCodes"
          :camera-index-code="cameraIndexCode"
          :config="config"
          :width="w"
          :height="h"
          :x="x"
          :y="y"
          :widgetInstanceId="widgetInstanceId"
          :videoId="`${widgetInstanceId}_0`"
          :componentStyle="componentStyle"
          :winContainerPid="winContainerPid"
          :isDesignView="isDesignView"
          :isMashupPreviewVideo="isPreviewVideo"
        />
      </div>
    </div>
    <!-- 事件播放 -->
    <el-dialog
      v-model="isShowHikvisionVideoEventDialog"
      :width="popVideoWidth"
      align-center
      append-to-body
      :draggable="false"
      class="hikvision-nvr-event-dialog is-in-modal"
      :class="`${xvueNameSpace}`"
      :style="{
        height: popVideoHeight + 'px',
      }"
      modal
      title="预览"
      @close="onClickCloseEventPlayerHandler"
    >
      <div :class="`video-haikan-refresh video-haikan-refresh-${componentStyle}`" @click="refreshEventVideo">
        <el-icon>
          <Refresh />
        </el-icon>
      </div>
      <haikang-video
        v-if="isShowEventPlayer"
        ref="haikanVideoRef"
        :prop-camera-index-codes="propCameraIndexCodes"
        :camera-index-code="cameraIndexCode"
        :config="config"
        :width="w"
        :height="h"
        :x="x"
        :y="y"
        is-in-dialog="1"
        :widgetInstanceId="widgetInstanceId"
        :videoId="`${widgetInstanceId}_0`"
        :componentStyle="componentStyle"
        :winContainerPid="winContainerPid"
        :isDesignView="isDesignView"
        :isMashupPreviewVideo="isPreviewVideo"
      />
      <div class="btn-box">
        <el-button @click="onClickCloseEventPlayerHandler(true)">关闭</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import apis from '@/apis/hikivision-video.js';
import Icon from '@/components/common/icon/icon.vue';
import chartBase from '@/mixin/chart-base.js';
import emitComponentBase from '@/mixin/emit-component-base.js';
import iconChartBase from '@/mixin/icon-chart-base.js';
import { EMIT_PARAMS_OBJ } from '@/utils/constant';
import { $message, isPromise } from '@/utils/util';
import { nextTick } from 'vue';
import { mapMutations, mapState } from 'vuex';
import configFile from './config/config';
import haikangVideo from './video';

export default {
  name: 'HaikanVideo',
  components: {
    haikangVideo,
    Icon,
  },
  mixins: [chartBase, iconChartBase, emitComponentBase],
  inject: ['provideObj'],
  props: ['pareentId', 'widgetId', 'widgetInstanceId', 'widgetName', 'identifier', 'w', 'h', 'x', 'y', 'isDesignView'],
  data() {
    return {
      xvueNameSpace: process.env.xvueNameSpace, // 给挂载在body下的元素加上主类名
      orgConfig: [],
      config: null,
      isShow: false,
      cameraIndexCode: '',
      propCameraIndexCodes: [],
      icon: {},
      componentStyle: 'light',
      displayStyle: 'flat',
      popVideoWidth: 360,
      popVideoHeight: 250,
      isPreviewVideo: false,
      visible: false,
      toggleTimer: null,
      toggleEventTimer: null,
      isDisplay: false,
      injectCameraIndexCodes: (this.provideObj && this.provideObj.provideCameraIndexCodes) || '',
      isShowHikvisionVideoEventDialog: false,
      isShowEventPlayer: false,
      isReceivedEvent: false,
      videoLayout: [
        '1x1',
        '1x2',
        '1+2',
        '2x2',
        '1x4',
        '1+5',
        '3+4',
        '1+7',
        '1+8',
        '1+9',
        '3x3',
        '1+12',
        '4+9',
        '1+1+12',
        '4x4',
        '1+16',
        '4x6',
        '5x5',
      ],
    };
  },
  computed: {
    ...mapState({
      cameraConfigs: state => state.VisualComponentsModule.cameraConfigs,
    }),
    cameraConfig() {
      const emptyConfig = {
        widgetInstanceId: this.widgetInstanceId,
        cameraIndexCodes: '',
      };
      return (this.cameraConfigs && this.cameraConfigs[this.widgetInstanceId]) || emptyConfig;
    },
    boxStyle() {
      let { backgroundColor } = this.getCssStyle('box');
      if (this.displayStyle === 'icon') {
        backgroundColor = 'rgba(255,255,255,0) !important';
      }
      return { backgroundColor };
    },
  },
  watch: {
    cameraIndexCode(newVal, oldVal) {
      if (newVal && oldVal && newVal !== oldVal) {
        if (this.displayStyle === 'flat' && !this.isReceivedEvent) {
          this.reloadVideo();
        }
      }
    },
    propCameraIndexCodes: {
      handler(newVal, oldVal) {
        if (newVal && oldVal && newVal !== oldVal) {
          if (this.displayStyle === 'flat' && !this.isReceivedEvent) {
            this.reloadVideo();
          }
        }
      },
      deep: true,
    },
  },
  created() {
    this.orgConfig = configFile;
    this.config = JSON.parse(JSON.stringify(configFile));
    this.chartId = `${this.widgetInstanceId}_01`;
    if (this.injectCameraIndexCodes) {
      this.propCameraIndexCodes = String(this.injectCameraIndexCodes).split(',');
      [this.cameraIndexCode] = this.propCameraIndexCodes;

      // 向属性面板传数据
      this.cameraConfig.widgetInstanceId = this.widgetInstanceId;
      this.cameraConfig.cameraIndexCodes = this.injectCameraIndexCodes;
      this.setCameraConfigs(this.cameraConfig);
    }
    this.isDisplay = window._adoPremise.haikanVideoJSLoaded ? true : false;
  },
  mounted() {
    if (location.host.indexOf('localhost') > -1) {
      this.loadWidget();
    }
  },
  beforeUnmount() {
    this.delCameraConfigs(this.widgetInstanceId);
    this.destoryHaiKan();
  },
  methods: {
    ...mapMutations(['setCameraConfigs', 'delCameraConfigs']),

    // 初始加载时 以及 编排面更改配置时 触发
    loadWidget(pageStatus) {
      this.pageStatus = pageStatus;
      if (!window._adoPremise.haikanVideoJSLoaded) {
        this.loadDependencies();
      } else {
        setTimeout(() => {
          this.isDisplay = true;
        }, 1000);
      }

      this.updateConfigData();
      this.afterLoadWidget();

      this.isReceivedEvent = false;
      this.isShowHikvisionVideoEventDialog = false;

      if (this.isSendEvent(pageStatus)) {
        if (this.displayStyle === 'flat') {
          this.isShow = true;
        }

        this.updateConfigProperty(pageStatus, this.getEventObj(pageStatus));
      } else {
        this.updateConfigProperty();
      }
    },
    // 加载第三方js文件，目前的代码是通过调取接口的方式，如果想自行导入也可以，js文件就在public文件夹中
    loadDependencies() {
      window._adoPremise.getCoalThirdJsKeyByAPIPromise?.then(() => {
        const hkJsencryptPromise = window._adoPremise.jsencrypt_loadJSScriptPromise;
        const hkWebControlPromise = window._adoPremise.control_loadJSScriptPromise;
        if (
          hkJsencryptPromise &&
          isPromise(hkJsencryptPromise) &&
          hkWebControlPromise &&
          isPromise(hkWebControlPromise)
        ) {
          this.dealDependencies(hkJsencryptPromise, hkWebControlPromise);
        } else {
          $message({
            message: this.$demoi18n('third.dependencyError'),
            type: 'error',
          });
        }
      });
    },
    dealDependencies(hkJsencryptPromise, hkWebControlPromise) {
      Promise.all([hkJsencryptPromise, hkWebControlPromise]).then(([hkJsencrypt, hkWebControl]) => {
        if (hkJsencrypt.code === 200 && hkWebControl.code === 200) {
          this.isDisplay = true;
          window._adoPremise.haikanVideoJSLoaded = true;
        } else if (hkJsencrypt.code === 404 || hkWebControl.code === 404) {
          $message({
            message: this.$demoi18n('third.dependencyEmpty'),
            type: 'warning',
          });
        } else {
          $message({
            message: this.$demoi18n('third.dependencyError'),
            type: 'warning',
          });
        }
      });
    },
    isSendEvent(obj) {
      for (const _key in obj) {
        if (!Object.prototype.hasOwnProperty.call(obj, _key)) {
          continue;
        }
        if (_key.indexOf(EMIT_PARAMS_OBJ) > -1) {
          if (obj[_key].parameters && obj[_key].parameters['thing_id']) {
            return true;
          }
        }
      }
      return false;
    },
    getEventObj(obj) {
      let params = {};

      for (const _key in obj) {
        if (_key.indexOf(EMIT_PARAMS_OBJ) > -1) {
          const o = obj[_key];
          if (o.eventKey) {
            const event = this.config.events.find(e => e.type === 'in' && e.key === o.eventKey);
            if (event) {
              params = event;
            }
            break;
          }
        }
      }

      return params;
    },
    acceptEvtMsg(paramters, key, obj) {
      let flag = false;
      let params = {};

      for (const _key in obj) {
        if (_key.indexOf(EMIT_PARAMS_OBJ) > -1) {
          const o = obj[_key];
          if (o.eventKey) {
            const event = this.config.events.find(e => e.type === 'in' && e.key === o.eventKey);
            if (event) {
              flag = true;
              params = event;
            }
            break;
          }
        }
      }
      if (flag) {
        this.isReceivedEvent = true;
        this.$nextTick(() => {
          this.updateConfigProperty(obj, params);
        });
      }
    },
    async updateConfigProperty(obj, paramsObj) {
      const {
        componentStyle,
        displayStyle,
        icon,
        cameraIndexCodes,
        popVideoWidth,
        popVideoHeight,
        isPreviewVideo,
      } = this.config.config.property;
      this.componentStyle = componentStyle;
      this.displayStyle = displayStyle;
      this.icon = icon;
      this.popVideoWidth = parseInt(popVideoWidth ? popVideoWidth : 360);
      this.popVideoHeight = parseInt(popVideoHeight ? popVideoHeight : 250);
      this.isPreviewVideo = isPreviewVideo;

      if (cameraIndexCodes) {
        this.propCameraIndexCodes = cameraIndexCodes.split(',');
        this.cameraIndexCode = this.propCameraIndexCodes[0];
      }

      let getParamKey = 'thing_id';
      paramsObj?.dbFields?.forEach(({ dbField, paramKey }) => {
        if (dbField === 'thing_id' && paramKey) {
          getParamKey = paramKey;
        }
      });
      const paramKey = paramsObj?.dbFields?.length ? getParamKey : 'thing_id';

      if (obj) {
        Object.keys(obj).forEach(async k => {
          const emitObj = obj[k];
          let flag = false;
          if (emitObj && emitObj.eventKey && k.indexOf(EMIT_PARAMS_OBJ) > -1) {
            const event = this.config.events.find(e => e.type === 'in' && e.key === emitObj.eventKey);
            if (event) {
              flag = true;
            }
          }
          if (flag && obj[k].parameters.thing_id) {
            const thingId = String(obj[k].parameters[paramKey]);

            let sourceId = '';

            // 视频源编码--视频通道编码
            if (thingId.indexOf('--') > -1) {
              sourceId = thingId.split('--')[0];
            }

            if (!sourceId && !this.config.config.property.appkey) {
              this.$message({
                type: 'error',
                message: '未查到视频源列表',
              });
            } else {
              this.processMonitorSourceInfo(sourceId, thingId);
            }
          }
        });
      }
    },
    async processMonitorSourceInfo(sourceId, thingId) {
      let host = this.config.config.property.ip;
      let appKey = this.config.config.property.appkey;
      let appSecret = this.config.config.property.secret;

      if (sourceId) {
        const data = await this.getHikivisionMonitorSourceInfo({ sourceId });
        host = data.host;
        appKey = data.appKey;
        appSecret = data.appSecret;
      }

      if (!host || !appKey || !appSecret) {
        this.$message({
          type: 'error',
          message: '视频源对接信息有误',
        });
      } else {
        let cameraIndexCodes = '';
        if (thingId.indexOf('--') > -1) {
          cameraIndexCodes = thingId.split('--')[1];
        } else {
          cameraIndexCodes = thingId;
        }

        if (!this.config.config.property.appkey) {
          this.config.config.property.ip = host;
          this.config.config.property.appkey = appKey;
          this.config.config.property.secret = appSecret;
          this.config.config.property.sourceId = sourceId;
        }

        this.propCameraIndexCodes = cameraIndexCodes.split(',');
        [this.cameraIndexCode] = this.propCameraIndexCodes;

        // 向属性面板传数据
        this.cameraConfig.widgetInstanceId = this.widgetInstanceId;
        this.cameraConfig.cameraIndexCodes = thingId;
        this.setCameraConfigs(this.cameraConfig);

        // 重新计算视频布局
        this.reCalcVideoLayout();

        if (this.isReceivedEvent) {
          this.isShowHikvisionVideoEventDialog = true;
          setTimeout(() => {
            this.reloadEventVideo();
          }, 1000);
        } else {
          this.reloadVideo();
        }
      }
    },
    reCalcVideoLayout() {
      const indexCodeNum = this.propCameraIndexCodes.length;
      const { videoLayout } = this;
      let layout = '';

      for (let i = 0; i < videoLayout.length; i++) {
        const layoutStr = videoLayout[i];

        if (layoutStr.indexOf('x') > -1) {
          const [first, second] = layoutStr.split('x');
          const val = first * second;

          if (indexCodeNum <= val) {
            layout = layoutStr;
            break;
          }
        }

        if (layoutStr.indexOf('+') > -1) {
          const addList = layoutStr.split('+');
          const addVal = addList.reduce((prev, next) => {
            const sum = prev + Number(next);
            return sum;
          }, 0);

          if (indexCodeNum <= addVal) {
            layout = layoutStr;
          }
        }
      }

      // 超过最大布局个数
      if (!layout) {
        layout = '5x5';
      }

      this.config.config.property.videLayout = layout;
    },
    async getHikivisionMonitorSourceList() {
      const res = await apis.getHikivisionMonitorSourceList();

      if (res.data.code === 200) {
        if (res.data.data && res.data.data.length > 0) {
          return res.data.data[0].sourceId;
        } else {
          return '';
        }
      } else {
        return '';
      }
    },
    async getHikivisionMonitorSourceInfo(params) {
      const res = await apis.getHikivisionMonitorSourceInfo(params);

      if (res.data.code === 200) {
        if (res.data.data) {
          return res.data.data;
        } else {
          return {};
        }
      } else {
        return {};
      }
    },
    hideVideo() {
      this.isShow = false;
    },
    showVideoDialog() {
      this.isShow = true;
    },
    refreshVideo() {
      if (this.toggleTimer) {
        return;
      }
      this.isShow = false;
      nextTick(() => {
        this.isShow = true;
      });
      this.toggleTimer = setTimeout(() => {
        // 等4秒后点击才有效
      }, 4000);
    },
    refreshEventVideo() {
      if (this.eventToggleTimer) {
        return;
      }
      this.isShowEventPlayer = false;
      nextTick(() => {
        this.isShowEventPlayer = true;
      });
      this.eventToggleTimer = setTimeout(() => {
        // 等4秒后点击才有效
      }, 4000);
    },
    reloadVideo() {
      this.isShow = false;

      if (this.reloadVideoTimer) {
        clearTimeout(this.reloadVideoTimer);
      }

      this.reloadVideoTimer = setTimeout(() => {
        this.isShow = true;
        this.reloadVideoTimer = null;
      }, 1500);
    },
    reloadEventVideo() {
      this.isShowEventPlayer = false;

      if (this.reloadEventVideoTimer) {
        clearTimeout(this.reloadEventVideoTimer);
      }

      this.reloadEventVideoTimer = setTimeout(() => {
        this.isShowEventPlayer = true;
        this.reloadEventVideoTimer = null;
      }, 1500);
    },
    destoryHaiKan() {
      const ref = this.$refs.haikanVideoRef;
      if (ref) {
        ref.destroyedVideo();
      }
    },
    onClickCloseEventPlayerHandler(closeDialog = false) {
      if (closeDialog) {
        this.isShowHikvisionVideoEventDialog = false;
      }

      this.isShowEventPlayer = false;
    },
  },
};
</script>
<style lang="less" scoped>
@import '../../common/chart.less';
.haikan-video {
  width: 100%;
  height: 100%;
}
:deep(.el-carousel) {
  .el-carousel__indicators {
    .el-carousel__button {
      background-color: #c0c4cc;
    }
    .el-carousel__indicator--vertical {
      padding: 4px 4px;
    }
  }
}
.content {
  height: 100%;
}
.video-group-container {
  height: 100%;
  width: 100%;
  position: relative;
}
.icon-container {
  .icon-content {
    display: inline-block;
    cursor: pointer;
  }
}
.video-haikan-refresh {
  position: absolute;
  right: 10px;
  top: 4px;
  font-size: 20px;
  color: blue;
  &-dark {
    color: #4ab9ff;
  }
  &-real {
    color: #00b8ff;
  }
}
.dark {
  .video-container {
    .video-name {
      color: #ffffff;
    }
  }
}
.real {
  .video-container {
    .video-name {
      color: #c9c9c9;
    }
  }
}
</style>
<style lang="less">
.hostsdk-video-popper {
  .video-group-container {
    max-height: 680px;
    overflow: auto;
  }
  ::-webkit-scrollbar {
    width: 4px !important;
    height: 4px !important;
  }
}
.hostsdk-video-popper-dark {
  background-color: #0d263a;
  border-color: #0d263a;
  color: #ffffff;
  opacity: 0;
  .popper__arrow {
    border-left-color: #116584 !important;
    border-right-color: #116584 !important;
    border-top-color: transparent !important;
    border-bottom-color: transparent !important;
    &::after {
      border-left-color: #122b40 !important;
      border-right-color: #122b40 !important;
      border-top-color: transparent !important;
      border-bottom-color: transparent !important;
    }
  }

  ::-webkit-scrollbar-thumb {
    background-color: #00f0ff !important;
  }

  ::-webkit-scrollbar-track {
    background-color: #1a405f !important;
  }

  ::-webkit-scrollbar-corner {
    background-color: #1a405f !important;
  }
}
.hostsdk-video-popper-light {
  ::-webkit-scrollbar-track {
    background-color: #efefef;
  }

  ::-webkit-scrollbar-thumb {
    background-color: #65c7f8;
  }

  ::-webkit-scrollbar-corner {
    background-color: #efefef;
  }
}

.hikvision-nvr-event-dialog {
  display: flex;
  flex-direction: column;
  height: calc(100% - 40px);

  .el-dialog__body {
    position: relative;
    display: flex;
    flex-direction: column;
    flex: 1;
    padding-top: 10px;
    padding-bottom: 10px;

    .video-haikan-refresh {
      right: 17px;
      top: -16px;
    }

    .btn-box {
      margin-top: 10px;
      text-align: center;
    }
  }

  &.is-in-modal {
    width: 100% !important;
    height: 100% !important;
    box-shadow: none !important;
    margin: 0;

    .el-dialog__header {
      display: none !important;
    }

    .el-dialog__body {
      padding: 0 !important;
      padding-top: 25px !important;
      background-color: #fff !important;

      .video-haikan-refresh {
        right: 14px !important;
        top: 2px !important;
      }
    }
  }
}
</style>
